moddbfandomcom-20200213-history
DirectX:Direct3D:Tutorials:VBNET:DX9:Initialization
Managed Direct3D 9 Initialization Goal In this tutorial, we will initialize Direct3D and write out a loop that will contain the bones of a function to draw graphics. We won’t actually draw anything, but the code in this tutorial will be used as a base for more advanced tutorials, so read this first. This tutorial is only about Direct3D, so we’re assuming you are familiar with Visual Basic.NET and basic graphics theory. Preparation Before we write any code, there are a few things that need to be done. First, you must reference the appropriate Managed DirectX dll’s. We will be using Microsoft.DirectX.dll, and Microsoft.DirectX.Direct3D.dll. After you have these referenced, change your form’s KeyPreview property to True. Now, we need to add some Imports statements at the very top of your code, before your form’s class declaration. This will make it easier to access DirectX 9's functionality. Imports Microsoft.DirectX Imports Microsoft.DirectX.Direct3D Now, we need to tell our program that we’ll be handling all the graphics for our form. In your form’s constructor (Public Sub New), add this line of code after everything else that’s there: 'This line is necessary to keep flickering down. Me.SetStyle(ControlStyles.UserPaint Or ControlStyles.AllPaintingInWmPaint _ Or ControlStyles.Opaque, True) This effectively tells Windows to butt out of the display process. If you are using Microsoft Visual Studio, you will have to expand the Windows Form Designer Generated Code region to find your form’s constructor. After you’ve added the line of code, it should look like this: #Region " Windows Form Designer generated code " Public Sub New() MyBase.New() 'This call is required by the Windows Form Designer. InitializeComponent() 'Add any initialization after the InitializeComponent() call 'This line is necessary to keep flickering down. Me.SetStyle(ControlStyles.UserPaint Or ControlStyles.AllPaintingInWmPaint _ Or ControlStyles.Opaque, True) End Sub Now we’re ready to initialize DirectX. Initializing DirectX First, we need to make two Private variables. At the top of your class, right under the Inherits statement, add this declaration: 'The GraphicsDevice object represents the user's graphics card Private GraphicsDevice As Direct3D.Device = Nothing 'The presentation parameters object tells our device how it should function Private presentParams As PresentParameters = New PresentParameters The GraphicsDevice object is an instance of Direct3D.Device, and it will represent the user’s graphics card. The presentParams object is an instance of the PresentParameters object, which holds information which we use to modify the behavior of our GraphicsDevice object. Now, we need to create a method called CreateGraphics to initialize our GraphicsDevice object. Private Sub InitializeGraphics() 'set our presentation parameters presentParams.SwapEffect = SwapEffect.Discard ' use the users current display mode Dim current As Format = Direct3D.Manager.Adapters(0).CurrentDisplayMode.Format 'Check to see if fullscreen mode is supported before you use it. If Direct3D.Manager.CheckDeviceType(0, Direct3D.DeviceType.Hardware, current, current, False) Then ' Perfect, this is valid presentParams.Windowed = False presentParams.BackBufferFormat = current presentParams.BackBufferCount = 1 presentParams.BackBufferWidth = 800 'this is the resolution of your display presentParams.BackBufferHeight = 600 Else 'If it doesn't supports fullscreen mode, go windowed presentParams.Windowed = True End If 'Create our device GraphicsDevice = New Direct3D.Device(0, Direct3D.DeviceType.Hardware, Me, _ CreateFlags.SoftwareVertexProcessing, presentParams) End Sub It’s a nice healthy chunk of code. First, we told the presentParams object to use SwapEffect.Discard. This means that your graphics device will simply discard the contents of the back buffer if it is not ready to present the graphical data to the screen. The second line created an object called current which holds the user’s current display format. Without going into too much detail, this is basically just the color depth. Next, we want to initialize the graphics card in full-screen mode. First, though, we should check to make sure the user’s graphics card will support it. The settings we pass to CheckDeviceType will be explained later when we actually initialize the device with these settings. If full-screen mode is supported, we set windowed mode to false, and the backbuffer format to the users current display format. We give the device one backbuffer, and set the screen width and height to whatever strikes our fancy. If the user’s graphics card doesn’t support full-screen mode, we set windowed mode to true. At long last, we initialize the GraphicsDevice object. The first parameter is the adapter number of the graphics card we want to use. For our purposes, 0 is fine. The next parameter tells our GraphicsDevice object what kind of device it represents. We want to use a literal piece of hardware—the graphics card— so we use DeviceType.Hardware. The third parameter tells the device where to present (draw) the graphics. We want it to use our form, so we pass Me. The fifth parameter tells the graphics device whether we want the vertex processing to be done on the graphics card, or on the users CPU via software. You can count on software vertex processing being supported, but hardware is faster. When developing professionally, you should check to see if hardware is supported, and use it whenever you can. Finally, we pass our presentParams object, which tells the device how to present the graphical data we send it. The Game Loop Now that we’ve finished writing our InitializeGraphics routine, we need to call it. When making games, it’s often easiest to make your own entry point for your application. We’ll create a shared sub called Main, as shown below. Shared Sub Main() 'The playarea object is an instance of our form. Dim PlayArea As New Form1 PlayArea.Show() 'Show the form. PlayArea.InitializeGraphics() 'Initialize all the graphical elements Try While PlayArea.Created 'The Game loop PlayArea.Render() 'This will be used to display all of our graphics Application.DoEvents() 'This gives Windows a chance to do its stuff. End While Finally PlayArea.Dispose() 'Clean up our form when we are done. End Try End Sub Note: More information on a better renderloop can be found here or on Tom Miller's blog My last post on render loops (hopefully)... After you have this written out, bring up the dialog box for you project’s properties. Change the startup object from Form1 to Sub Main. Now your program will start by running the code in sub Main. The code in sub Main is pretty simple. We create a new instance of our form called PlayArea, we show it, and we call its InitializeGraphics method. While our PlayArea window still exists, we continuously call the Render method (which we still need to write), and allow Windows to process any other events that have been sent to our window. When PlayArea is closed, the PlayArea object is disposed, releasing the resources it consumes. A Base Subroutine For Rendering We aren’t actually going to draw anything in this tutorial, but we still will make the bones of a Render subroutine for use in future tutorials. Enter the code shown below. Private Sub Render() 'Clear the screen black GraphicsDevice.Clear(ClearFlags.Target, System.Drawing.Color.Black, 1.0F, 0) 'All drawing goes in between the BeginScene and EndScene statements GraphicsDevice.BeginScene() GraphicsDevice.EndScene() 'present all graphical information to the user’s screen GraphicsDevice.Present() End Sub First we clear the screen with black. In the future, we will put all drawing code in between the BeginScene and EndScene statements. By themselves, they do nothing. At the end, we tell the device to present all the drawing done between the two scene statements to the user’s screen. A Way To Exit We’re almost done. All we need now is a way to get out of this program. We’ll make the escape key exit the program. Add this code to your form’s KeyDown Event: If e.KeyCode = Keys.Escape Then 'Close the window when the user presses escape Me.Close() 'yes, close, not dispose. End If This should be familiar. We used Me.Close instead of Me.Dispose because we already dispose the window in Sub Main. If your run the program now, you should see an exciting black screen. That’s it! If you have any questions, you can ask them on the forums. ---- External Links: Jason Zurowski's Simple Direct3D Initialization Tutorial